home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
satellit
/
radserv
/
radsrv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-23
|
17KB
|
625 lines
/* %W% %E% %U% */
/*
* VersaTrack Radio Control Server Template.
*
* This code DOES NOT CONTROL ANY EXTERNAL DEVICE.
*
* This is a just skeleton program that shows how to communicate with
* VersaTrack. The code for reading/writing an NT-supported COM port
* is and also provided. It can be used as a starting point to develop
* a radio or rotator control server (or similar program.)
*
* ALL DISCLAIMERS APPLY! THIS PROGRAM IS PROVIDED FREE AND AS IS.
* YOU USE IT ENTIERLY AT YOU OWN RISK. IN NO EVENT THE AUTHOR SHALL BE
* LIABLE FOR ANY DIRECT, IMPLIED OR CONSEQUENTIAL DAMAGE ARISING OUT OF
* OR RELATED TO ITS USE. THERE IS NO WARANTY OR SUPPORT AND THE AUTHOR
* DOES NOT MAKE ANY REPRESENTATION, INCLUDING BUT NOT LIMITED TO THOSE
* OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "resource.h"
#include "radextrn.h"
char textbuf[BUFLEN];
char tmpbuf[BUFLEN];
char msgbuf[BUFLEN];
char VersionStr[48];
HANDLE hInst; /* Instance handle */
HANDLE ServerThread; /* server thread handle */
HWND Gwnd; /* global copy of our window handle */
HWND vsthwnd; /* global copy of versatrk window hanlde*/
HWND rdhwnd; /* handle of radio display dialog box */
DWORD vstth; /* handle of versatrk's main thread */
DWORD vstpid; /* gloabl copy of versatrk process ID */
HCURSOR hcurSave; /* Last cursor */
HCURSOR hWait; /* handle of hourglass cursor icon */
HICON hAsterisk, hQuestion; /* dialog box decorations */
int srv_state; /* Server State */
BOOL NoClientOk; /* If non-zero, go on w/out client present */
HANDLE pipeh; /* pipe handle to Versatrack client */
CRITICAL_SECTION VstLock; /* Lock to update VST window ID */
void nullfunc(va_list vlist, ...) { }
void (*diag)(va_list vlist, ...);
int WINAPI WinMain(hInst, hPrevInst, CmdLinePtr, CmdShow)
HANDLE hInst, hPrevInst;
char *CmdLinePtr;
int CmdShow;
{
MSG msg;
extern BOOL InitInstance(HANDLE, HANDLE, int);
extern BOOL InitApplication(HANDLE);
diag = nullfunc;
hInst = hInst;
NoClientOk = FALSE;
if (!InitApplication(hInst))
return 1;
if (!InitInstance(hInst, hPrevInst, CmdShow))
return 1;
while (GetMessage(&msg, (UINT)NULL, (UINT)NULL, (UINT)NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL InitApplication(hInst)
HANDLE hInst;
{
WNDCLASS wc;
extern BOOL CALLBACK MainWndProc();
BOOL r;
wc.style = CS_OWNDC ;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RADICON));
wc.hCursor = hcurSave = LoadCursor(NULL, IDC_CROSS);
wc.hbrBackground = GetStockObject(GRAY_BRUSH);
wc.lpszMenuName = MAKEINTRESOURCE(IDR_RAD_MENU);
wc.lpszClassName = "VSTRADIOSRV";
r = RegisterClass(&wc);
hAsterisk = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ASTERISK));
hQuestion = LoadIcon(NULL, MAKEINTRESOURCE(IDI_QUESTION));
hWait = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
InitializeCriticalSection(&VstLock);
sprintf(VersionStr,"Radio Cntl Skeleton Sample");
return r;
}
BOOL InitInstance(hInstance, hPrev, CmdShow)
HANDLE hInstance, hPrev;
int CmdShow;
{
HWND hWnd;
hInst = hInstance;
hWnd = CreateWindow("VSTRADIOSRV", "Radio Cntl Skeleton Sample",
WS_OVERLAPPEDWINDOW | WS_BORDER | WS_CLIPCHILDREN,
0, 0, 300, 100, NULL, NULL, hInst, NULL );
if (hWnd == NULL)
return FALSE;
Gwnd = hWnd;
UpdateWindow(hWnd);
ShowWindow(hWnd, SW_SHOWMINIMIZED);
return TRUE;
}
BOOL CALLBACK
MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int cmd;
extern BOOL SaveParams(void);
extern BOOL TTYProc(tty_t *);
extern BOOL ReadParams(void);
extern BOOL CALLBACK RadioDisplay(HWND, UINT, WPARAM, LPARAM);
Gwnd = hWnd;
switch (message) {
case WM_CREATE:
if (!GetSystemMetrics(SM_MOUSEPRESENT))
fatal("Radio server requires the use of a mouse");
#ifdef _DEBUG_
diag = DebugFunc;
diag("Debug console opened.\n");
#endif /* _DEBUG_ */
ReadParams();
if (!ServerCreate())
fatal("Unable to create service thread");
break;
case WM_TIMER:
cmd = LOWORD(wParam);
switch (cmd) {
case IDT_HEARTBEAT:
if (NoClientOk) {
KillTimer(hWnd, IDT_HEARTBEAT);
break;
}
if (!VstIsAlive()) {
#ifdef _DEBUG
diag("Lost VersaTrack Heartbeat\n");
#endif /* _DEBUG_ */
KillTimer(hWnd, IDT_HEARTBEAT);
PostMessage(hWnd, CNTRL_CLIENTEXIT, (WPARAM)0, (LPARAM)0);
}
break;
default:
break;
}
break;
case SERVER_CLIENTINIT: /* received as a result of a "hello" */
VST_LOCK();
vsthwnd = (HWND) lParam;
vstth = vstpid = 0L;
vstth = GetWindowThreadProcessId(vsthwnd, &vstpid);
VST_UNLOCK();
NoClientOk = FALSE;
/* Check every 5 secs to see if VersaTrack is alive */
SetTimer(hWnd, IDT_HEARTBEAT, (DWORD) 5000, (TIMERPROC) NULL);
break;
case WM_CANCELMODE:
ReleaseCapture();
break;
case WM_COMMAND:
cmd = LOWORD(wParam);
switch (cmd) {
case IDM_OPTIONS_COMPORT:
PortParams();
break;
case IDM_OPTIONS_SETTINGS:
RadioParams();
break;
case IDM_OPTIONS_SAVESETTINGS:
SaveParams();
break;
case IDM_ACTIVATE:
if (!TTYProc(&rigInfo.tty))
usermsg("connection to radio failed");
if (!rdhwnd)
rdhwnd = CreateDialog(hInst,
MAKEINTRESOURCE(IDD_RADIO_DISPLAY), hWnd, RadioDisplay);
break;
case IDM_DEACTIVATE:
if (rdhwnd) {
DestroyWindow(rdhwnd);
rdhwnd = NULL;
}
break;
default:
break;
}
break;
case WM_MOUSEACTIVATE:
return MA_ACTIVATE;
case WM_CLOSE:
KillTimer(hWnd, IDT_HEARTBEAT);
goto defaction;
case CNTRL_CLIENTEXIT:
if (!yesno("No VersaTrack Heartbeat! Do you wish to exit ?")) {
NoClientOk = TRUE;
break;
}
Sleep(0);
/* FALL THROUGH */
case WM_DESTROY:
KillTimer(hWnd, IDT_HEARTBEAT);
PostQuitMessage(0);
break;
default:
defaction:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0L;
}
static BOOL CALLBACK
RadUserMsg(hwnd, message, wParam, lParam)
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
int action;
POINT *p;
HDC hdc;
switch(message) {
case WM_INITDIALOG:
p = DialogPos(Gwnd, hwnd);
SendDlgItemMessage(hwnd, IDC_XMSGTEXT, WM_SETTEXT, 0, (LPARAM) msgbuf);
SetWindowPos(hwnd, HWND_TOPMOST, (int)p->x, (int)p->y, 0, 0,
SWP_NOSIZE|SWP_SHOWWINDOW);
/* FALL THROUGH */
case WM_PAINT:
hdc = GetDC(hwnd);
DrawIcon(hdc, 12, 17, hAsterisk);
ReleaseDC(hwnd, hdc);
break;
case WM_COMMAND:
action = LOWORD(wParam);
if (action == IDOK) {
EndDialog(hwnd, wParam);
return TRUE;
}
break;
}
return FALSE;
}
static BOOL CALLBACK
RadYesNo(hwnd, message, wParam, lParam)
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
int action;
POINT *p;
HDC hdc;
switch(message) {
case WM_INITDIALOG:
p = DialogPos(Gwnd, hwnd);
SendDlgItemMessage(hwnd, IDC_XYESNOTEXT, WM_SETTEXT, 0, (LPARAM) msgbuf);
SendMessage(hwnd, DM_SETDEFID, (WPARAM) IDOK, (LPARAM) 0);
SetWindowPos(hwnd, HWND_TOPMOST, (int)p->x, (int)p->y, 0, 0,
SWP_NOSIZE | SWP_SHOWWINDOW);
/* FALL THROUGH */
case WM_PAINT:
hdc = GetDC(hwnd);
DrawIcon(hdc, 14, 20, hQuestion);
ReleaseDC(hwnd, hdc);
break;
case WM_COMMAND:
action = LOWORD(wParam);
if (action == IDOK || action == IDCANCEL) {
EndDialog(hwnd, (LOWORD(wParam) == IDOK) ? TRUE : FALSE);
EnableWindow(GetParent(hwnd), TRUE);
return TRUE;
}
break;
}
return FALSE;
}
void
usermsg(msg)
char *msg;
{
int flag;
strcpy(msgbuf,msg);
if ((flag = IsIconic(Gwnd))) {
OpenIcon(Gwnd);
EnableWindow(Gwnd, TRUE);
}
DialogBox(hInst, MAKEINTRESOURCE(IDD_XMESSAGE), Gwnd, RadUserMsg);
if (flag)
CloseWindow(Gwnd);
else
EnableWindow(Gwnd, TRUE);
}
int
yesno(msg)
char *msg;
{
int r, flag;
strcpy(msgbuf,msg);
if (flag = IsIconic(Gwnd)) {
OpenIcon(Gwnd);
EnableWindow(Gwnd, TRUE);
}
r = DialogBox(hInst, MAKEINTRESOURCE(IDD_XYESNO), Gwnd, RadYesNo);
if (flag)
CloseWindow(Gwnd);
else
EnableWindow(Gwnd, TRUE);
return r;
}
void
fatal(s)
char *s;
{
char xbuf[256];
sprintf(xbuf,"ERROR: %s (code %d)",s,GetLastError());
usermsg(s);
ExitProcess(1);
}
POINT *
DialogPos(pwnd, cwnd)
HWND pwnd, cwnd; /* position cwnd in center of pwnd */
{
RECT pr,cr;
static POINT p;
int xmax,ymax;
if (pwnd == NULL)
pwnd = GetParent(cwnd);
xmax = GetSystemMetrics(SM_CXSCREEN);
ymax = GetSystemMetrics(SM_CYSCREEN);
GetClientRect(pwnd,&pr);
GetClientRect(cwnd,&cr);
p.x = p.y = 0;
ClientToScreen(pwnd,&p); /* upper left corner of parent on screen */
if ((p.x < 20) || (p.x + (pr.right - pr.left)) > xmax+20) {
pr.left = 0;
pr.right = xmax;
p.x = 0;
}
if ((p.y < 20) || (p.y + (pr.bottom - pr.top)) > ymax+20) {
pr.top = 0;
pr.bottom = ymax;
p.y = 0;
}
p.x += ((pr.right - pr.left) - (cr.right - cr.left)) / 2;
p.y += ((pr.bottom - pr.top) - (cr.bottom - cr.top)) / 2;
return &p;
}
void
NormCursor()
{
SetWindowText(Gwnd, VersionStr);
SetCursor(hcurSave);
SetClassLong(Gwnd, GCL_HCURSOR, (LONG) hcurSave);
}
void
WaitCursor()
{
SetCursor(hWait);
SetClassLong(Gwnd, GCL_HCURSOR, (LONG) hWait);
SetWindowText(Gwnd,"Waiting");
}
static BOOL
VstIsAlive()
{
int status;
VST_LOCK();
if (vsthwnd == NULL) {
VST_UNLOCK();
return FALSE;
}
/* If the post succeeds, VersaTrack thread is still there. It will
* simply read and discard the message. If it's not there, we'll get
* an error and PostThreadMessage() will return FALSE.
*/
status = PostThreadMessage(vstth, VST_PROBE_AYT, (WPARAM) 0, (LPARAM) Gwnd);
VST_UNLOCK();
return status;
}
static BOOL
ServerCreate()
{
long dummy;
extern void RadServerProc();
WaitCursor();
ServerThread = CreateThread ((LPSECURITY_ATTRIBUTES)NULL, (DWORD)0,
(LPTHREAD_START_ROUTINE)RadServerProc, (LPVOID)&Gwnd,
(DWORD)0, (LPDWORD)&dummy);
if (ServerThread == INVALID_HANDLE_VALUE)
ServerThread = NULL;
return ServerThread != INVALID_HANDLE_VALUE;
}
static void
RadServerProc(HWND *hWnd)
{
HANDLE hPipe, rdEvent;
BOOL done = FALSE;
HWND wid;
OVERLAPPED ovrlap;
PSECURITY_DESCRIPTOR sdp;
SECURITY_ATTRIBUTES sa, *sap;
int ret, error, nread, seq, update, lastseq;
static int vver, pver;
double melev, loss, az, el, range, rrate;
char inbuf[256];
char satname[48], sitename[64];
char reason[64], mode[6];
extern void r_control(char *, double, double, double, double);
extern void r_interrupt(char *, char *);
extern void r_init(char *, char *, char *, int);
extern void r_special(int);
extern void r_begin(HWND);
extern void r_end(HWND);
/* This should prevent server's access rights to the pipe to become
* inheritable. Not really needed for VersaTrack, but good
* prog. practice in general.
*/
sdp = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
sap = NULL;
if (sdp) {
InitializeSecurityDescriptor(sdp, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(sdp, TRUE, (PACL) NULL, FALSE);
sap = &sa;
}
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = sdp;
sa.bInheritHandle = FALSE;
hPipe = CreateNamedPipe ("\\\\.\\PIPE\\_VRADIO_",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE,
PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, sap);
if ( hPipe == INVALID_HANDLE_VALUE )
fatal("Service Thread: Can't create service pipe - Server Exiting");
rdEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset ((void *)&ovrlap, 0, sizeof(OVERLAPPED));
ovrlap.hEvent = rdEvent;
#ifdef _DEBUG_
diag("Pipe Created. Awaiting connection\n");
#endif /* _DEBUG_ */
again:
wid = NULL;
WaitCursor();
ConnectNamedPipe(hPipe, NULL);
NormCursor();
#ifdef _DEBUG_
diag("Pipe connected.\n");
#endif /* _DEBUG_ */
/* VersaTrack messages service loop */
do {
inbuf[0] = 0;
ret = ReadFile (hPipe, inbuf, 100, &nread, &ovrlap);
error = GetLastError();
if (ret == FALSE) {
switch (error) {
case ERROR_IO_PENDING:
WaitForSingleObject (rdEvent, (DWORD)-1);
break;
default:
#ifdef _DEBUG_
diag("Pipe I/O error (code %d) - Disconnecting...\n", GetLastError());
#endif /* _DEBUG_ */
DisconnectNamedPipe(hPipe);
Sleep(0);
r_end(wid);
goto again;
}
}
if (!done) {
if (!GetOverlappedResult (hPipe, &ovrlap, &nread, FALSE)) {
#ifdef _DEBUG_
diag("Pipe I/O error (code %d) - Disconnecting...\n", GetLastError());
#endif /* _DEBUG_ */
DisconnectNamedPipe(hPipe);
Sleep(0);
r_end(wid);
goto again;
}
/* Assume valid message and dispatch per message type */
inbuf[nread] = 0;
switch (inbuf[0]) {
case '+': /* NORMAL MODE MSG */
if (sscanf(inbuf+2,"%d AZ %lf EL %lf RNG %lf DV %lf PL %lf %s",
&seq, &az, &el, &range, &rrate, &loss, satname))
if (++lastseq == seq)
r_control(satname, el, range, rrate, loss);
break;
case '!': /* INTERRUPTION MSG */
if (sscanf(inbuf+2,"%d '%[^']'", &seq, reason))
if (++lastseq == seq)
r_interrupt(satname, reason);
break;
case '*': /* INITIALIZTION/RESET MSG */
mode[3] = 0;
if (sscanf(inbuf+2,"%d INIT UPD %d MIE %lf MD '%[^']' SITE '%[^']' SAT '%[^']'",
&seq, &update, &melev, mode, sitename, satname))
if (++lastseq == seq)
r_init(satname, sitename, mode, update);
break;
case '>': /* NEW CONNECTION FROM VERSATRACK */
if (sscanf(inbuf+2,"HELLO %d %d WH %x SEQ %d", &vver, &pver,
&wid, &seq)) {
PostMessage(Gwnd, SERVER_CLIENTINIT, (WPARAM)0, (LPARAM)wid);
lastseq = seq;
r_begin(wid);
}
break;
default:
break;
}
}
} while(!done);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
CloseHandle(rdEvent);
DeleteObject(rdEvent);
LocalFree(sdp);
#ifdef _DEBUG_
diag("server thread exiting...\n");
#endif /* _DEBUG_ */
ServerThread = NULL;
ExitThread(0);
}